﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

public enum RoomType
{
    None,
    Bathroom,
    LivingRoom,
    Kitchen,
    BedRoom,
    Office,
    DiningRoom
}

public class Room {

    private Point topLeftCorner = null;

    private List<Point> doors = new List<Point>(); //TODO: unsichtbaren block vor und nach ein-und ausgängen
    private List<Point> doorPlaceHolders = new List<Point>();

    // width and height of room in terms of grid
    private int width = 0;
	private int height = 0;

    private int xLeft = 0;
	private int xRight = 0;
	private int yTop = 0;
	private int yBottom = 0;

    private int roomNeighbourOffset = 3;

    private int groupPlacementDistance = 3;

    public bool furniturePlaced = false;
    private bool allInstancesPlaced = false;
    private bool rightType = false;
    private bool goAgain = false;

    private List<GameObject> doorPlaceholderGOs = new List<GameObject>();
    private List<GameObject> furnitureListRoot = new List<GameObject>();
    private List<GameObject> furnitureListSecond = new List<GameObject>();
    private List<GameObject> furnitureListThird = new List<GameObject>();
    private GameObject definiteFloor = null;

    private RoomType roomType = 0;

	// center point of the room
    private float centerX;
    private float centerY;
    private Point center;

    public Room(Point point, int width, int height)
    {

        xLeft = point.x;
        xRight = point.x + width - 1;
        yTop = point.y;
        yBottom = point.y - height + 1;

        this.topLeftCorner = new Point(point.x, point.y);
        this.width = width;
        this.height = height;
        centerX = (float)(xLeft + xRight) / 2 -0.5f;
        centerY = (float)(yTop + yBottom) / 2;
        center = new Point((xLeft + xRight) / 2, (yTop + yBottom) / 2);
        //center = new Point(Mathf.floor((x1 + x2) / 2),
        //    Mathf.floor((y1 + y2) / 2));
    }

	// return true if this room intersects provided room
	public bool intersects(Room room)
    {
        //return (xLeft <= room.GetXRight() && xRight >= room.GetXLeft() && yTop <= room.GetYBottom() && room.yBottom >= room.GetYTop());
        //if rooms can share one wall ->   < and > if each room should have his own walls ->   >= and <=
        return (xLeft < room.GetXRight() && xRight > room.GetXLeft() && yTop > room.GetYBottom() && room.yBottom < room.GetYTop());
	}

    public bool IsNeighbour(Room room)
    {
        if (this.Equals(room))
            return false;
        int y = 0;

        int neighbourCounter = 0;
        int x = xLeft;
        for (y = yBottom; y <= yTop; y++) //left side
        {
            if (room.IsPointInsideRoom(new Point(x, y)))
                neighbourCounter++;
        }
        if (neighbourCounter >= roomNeighbourOffset) //TODO: 2 is temporary value for offset
            return true;

        neighbourCounter = 0;
        x = xRight;
        for (y = yBottom; y <= yTop; y++) //right side
        {
            if (room.IsPointInsideRoom(new Point(x, y)))
                neighbourCounter++;
        }
        if (neighbourCounter >= roomNeighbourOffset)
            return true;

        neighbourCounter = 0;
        y = yTop;
        for (x = xLeft; x <= xRight; x++) //top side
        {
            if (room.IsPointInsideRoom(new Point(x, y)))
                neighbourCounter++;
        }
        if (neighbourCounter >= roomNeighbourOffset)
            return true;

        neighbourCounter = 0;
        y = yBottom;
        for (x = xLeft; x <= xRight; x++) //bottom side
        {
            if (room.IsPointInsideRoom(new Point(x, y)))
                neighbourCounter++;
        }
        if (neighbourCounter >= roomNeighbourOffset)
            return true;

        return false;
    }

    public bool IsPointInsideRoom(Point point)
    {
        return (point.x >= this.xLeft && point.x <= this.xRight && point.y <= this.yTop && point.y >= this.yBottom);
    }

    public void MarkRoomInMap()
    {
        MapOverview.Instance.MarkMapAsUsed(topLeftCorner.x, topLeftCorner.y, topLeftCorner.x + width - 1, topLeftCorner.y - height + 1);
    }

    public void SetDoorInRoom(Point doorPoint/*, Point placeHolder*/)
    {
        foreach (Point existingDoor in doors)
        {
            if (doorPoint.Equals(existingDoor))
            return;
        }
        doors.Add(doorPoint); //TODO: schauen ob das mit return läuft
    }

    public void SetDoorPlaceholderPosition(Point _placeholder) //Sets the coordinates for a placeholder !in front of! the door
    {
        doorPlaceHolders.Add(_placeholder);
    }

    public bool IsFloor(int x, int y)
    {
        return (x > xLeft && x < xRight && y < yTop && y > yBottom);
        //string[,] tiles = new string[width-2, height-2];
        //for (int i = x1; i <= x2; i++) //Da x Wert von links nach rechts größer wird
        //{
        //    for (int j = y1; j >= y2; j--) //Da y Wert von oben nach unten kleiner wird
        //    {
        //        tiles[i, j] = "w";
        //    }
        //}
    }

    public void Furnish(List<GameObject> suitableFurniture, List<GameObject> floor)
    {
        Clear();
        //FurniturePiece allo2 = suitableFurniture[2].GetComponent<FurniturePiece>();

        InsertDoorPlaceHolders();
        InsertTempWallObjects();
        InsertFloor(floor);
        //InsertDoorPlaceHolders();
        int maxRange = furnitureListRoot.Count;

        //while (true)
        //{
            //furniturePlaced = false;
            //goAgain = false;

            /*** Positioning on WALLS ***/
            foreach (GameObject suitableFurnitureElement in suitableFurniture)
            {
                    int loopCounter = 0;

                    int limit = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesInRoom()+1);
                    int randomNo = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), limit+1);
                    suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(randomNo);

                    while (loopCounter < 20)
                    {
                        int randomValue = UnityEngine.Random.Range(0, maxRange);
                        GameObject chosenRootObject = furnitureListRoot[randomValue];

                        //allInstancesPlaced = false;
                        //rightType = false;
                        foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face0)
                        {
                            if (face.furniture.Equals(chosenRootObject.GetComponent<FurniturePiece>().GetFurnitureType()))
                            {
                                GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                                gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
                                furnitureListSecond.Add(gameObjectTemp);

                                if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 0, chosenRootObject.GetComponent<FurniturePiece>(), definiteFloor, doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, false)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                                {
                                    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                    gameObjectTemp.GetComponent<FurniturePiece>().SwitchColliders();

                                    //suitableFurniture.GetComponent<FurniturePiece>().AddInstance();
                                }
                                else
                                {

                                    Debug.Log(suitableFurnitureElement.name + " " + "wall " + randomValue + " allInstancedPlaced " + allInstancesPlaced + " furniturePlaced " + furniturePlaced);
                                    GameObject.Destroy(gameObjectTemp);
                                }
                            }
                        }
                        foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face1)
                        {
                            if (face.furniture.Equals(chosenRootObject.GetComponent<FurniturePiece>().GetFurnitureType()))
                            {

                                if (suitableFurnitureElement.name.Contains("Bathtub"))
                                    Debug.Log("");
                                Debug.Log("new Element in loop");
                                GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                                gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
                                furnitureListSecond.Add(gameObjectTemp);


                                if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, chosenRootObject.GetComponent<FurniturePiece>(), definiteFloor, doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, false)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                                {
                                    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                    gameObjectTemp.GetComponent<FurniturePiece>().SwitchColliders();

                                }
                                else
                                {
                                    GameObject.Destroy(gameObjectTemp);                            //gameObjectTemp.TestForCollision(placedFurnitureElement);
                                }
                            }
                        }
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face2)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 2, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face3)
                        {
                            if (face.furniture.Equals(chosenRootObject.GetComponent<FurniturePiece>().GetFurnitureType()))
                            {
                                GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                                gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
                                furnitureListSecond.Add(gameObjectTemp);

                                if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 3, chosenRootObject.GetComponent<FurniturePiece>(), definiteFloor, doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, false)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                                {
                                    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                    gameObjectTemp.GetComponent<FurniturePiece>().SwitchColliders();
                                }
                                else
                                {

                                    Debug.Log(suitableFurnitureElement.name + " " + "wall " + randomValue + " allInstancedPlaced " + allInstancesPlaced + " furniturePlaced " + furniturePlaced);
                                    GameObject.Destroy(gameObjectTemp);
                                }
                            }
                        }
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face4)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 4, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face5)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 5, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        loopCounter++;

                        if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
                            break;
                    } //end of while
            } //end of foreach

            //bool definitiveMaxNumberSet = false;
            //foreach (GameObject placedFurnitureElement in furnitureListSecond)
            //{
            //    int loopCounter = 0;
            //    while (loopCounter < 5)
            //    {

            //        foreach (GameObject suitableFurnitureElement in suitableFurniture)
            //        {
            //            //List<MultiDimensionalFace> supportedFaces = new List<MultiDimensionalFace>(); //TODO: could be used if chairs, that have 4 constraints on one face for the table, want to be placed randomly on the edges
            //            if (!definitiveMaxNumberSet)
            //            {
            //                //suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(UnityEngine.Random.Range(2, suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesAsChild()));
            //                suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(7);
            //                Debug.Log(suitableFurnitureElement.name + " maxNumber: " + suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber());
            //                Debug.Log(suitableFurnitureElement.name + " maxInstancesAsChild " + suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesAsChild());
            //            }
            //            Component one = placedFurnitureElement.GetComponent<FurniturePiece>();
            //            Component two = suitableFurnitureElement.GetComponent<FurniturePiece>();

            //            foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face0)
            //            {
            //                if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
            //                    break;
            //                if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
            //                {
            //                    //supportedFaces.Add(face);

            //                    GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

            //                    gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred

            //                    //Component gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement.GetComponent<FurniturePiece>(), new Vector3(0, 0, 0), Quaternion.identity) as Component;

            //                    furnitureListThird.Add(gameObjectTemp);
            //                    FurniturePiece alooooo = gameObjectTemp.GetComponent<FurniturePiece>();
            //                    if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 0, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
            //                    {
            //                        suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
            //                    }
            //                    else
            //                        GameObject.Destroy(gameObjectTemp);
            //                }
            //            }
            //            foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face1)
            //            {
            //                if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
            //                    break;
            //                if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
            //                {
            //                    //supportedFaces.Add(face);

            //                    GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

            //                    gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
            //                    furnitureListThird.Add(gameObjectTemp);

                                //if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                                //{
                                //    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                //}
                                //else
                                //    GameObject.Destroy(gameObjectTemp);
                                //gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true);
                                //suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();


                                // gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                                //gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
                                //furnitureListThird.Add(gameObjectTemp);

                                //if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                                //{
                                //    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                //}
                                //else
                                //    GameObject.Destroy(gameObjectTemp);

                                //gameObjectTemp.TestForCollision(placedFurnitureElement);
                                //yield return new WaitForSeconds(1f);
                                //yield return new WaitForEndOfFrame();

                                //yield return new WaitForEndOfFrame();

                                //yield return new WaitForEndOfFrame();
                                //yield return null;
                                //gameObjectTemp.GetComponent<FurniturePiece>().CheckForCollisions();
                        //    }
                        //}
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face2)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 2, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face3)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 3, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face4)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 4, placedFurniture.GetComponent<FurniturePiece>());
                        //}
                        //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face5)
                        //{
                        //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
                        //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 5, placedFurniture.GetComponent<FurniturePiece>());
                        //}

            //        }
            //        definitiveMaxNumberSet = true;
            //        loopCounter++;
            //    }
            //}

            /*** Positioning on FLOOR ***/

            foreach (GameObject suitableFurnitureElement in suitableFurniture)
            {
                int loopCounter = 0;

                int limit = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesInRoom() + 1);
                int randomNo = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), limit + 1);
                suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(randomNo);

                while (loopCounter < 20)
                {
                    int randomValue = UnityEngine.Random.Range(0, maxRange);
                    GameObject chosenRootObject = furnitureListRoot[randomValue];

                    //allInstancesPlaced = false;
                    //rightType = false;
                    foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face5)
                    {
                        if (face.furniture.Equals(definiteFloor.GetComponent<FurniturePiece>().GetFurnitureType()))
                        {
                            Debug.Log("new Element in loop"); //TODO In dieser Schleife bleibt er manchmal stecken
                            GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                            gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
                            furnitureListSecond.Add(gameObjectTemp);

                            if (gameObjectTemp.GetComponent<FurniturePiece>().MoveOnFloor(face, 5, definiteFloor, doorPlaceholderGOs, furnitureListRoot, furnitureListSecond)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                            {
                                suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                                gameObjectTemp.GetComponent<FurniturePiece>().SwitchColliders();
                                //suitableFurniture.GetComponent<FurniturePiece>().AddInstance();
                            }
                            else
                            {
                                gameObjectTemp.GetComponent<FurniturePiece>().SwitchColliders();

                                Debug.Log(suitableFurnitureElement.name + " " + "wall " + randomValue + " allInstancedPlaced " + allInstancesPlaced + " furniturePlaced " + furniturePlaced);
                                //GameObject.Destroy(gameObjectTemp);
                            }
                        }
                    }
               
                    loopCounter++;

                    if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
                        break;
                } //end of while
            } //end of foreach

            /*** Positioning on OTHER OBJECTS ***/
            List<PossibleParent> possibleParentsFaces = new List<PossibleParent>();
            foreach (GameObject suitableFurnitureElement in suitableFurniture)
            {
                foreach (GameObject placedFurnitureElement in furnitureListSecond)
                {
                    foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face0)
                    {
                        if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
                        {
                            string connectingFace = face.connectingFace.ToString();

                           // Vector3 facePosOfPlannedParent = (Vector3)destinationObject.facesPos.GetValue(face.connectingFace); 

                            possibleParentsFaces.Add(new PossibleParent(face, 0, placedFurnitureElement.GetComponent<FurniturePiece>()));
                            placedFurnitureElement.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions();
                        }
                    }
                    foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face1)
                    {
                        if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
                        {
                            string connectingFace = face.connectingFace.ToString();

                            // Vector3 facePosOfPlannedParent = (Vector3)destinationObject.facesPos.GetValue(face.connectingFace); 

                            possibleParentsFaces.Add(new PossibleParent(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>()));
                            placedFurnitureElement.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions();
                        }
                    }
                }
                if (possibleParentsFaces.Count > 0)
                {
                    int limit = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesInRoom()+1);
                    int randomNo = UnityEngine.Random.Range(suitableFurnitureElement.GetComponent<FurniturePiece>().GetMinInstances(), limit+1);
                    suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(randomNo);

                    int loopCounter = 0;
                    while (loopCounter < 20)
                    {
                        if (suitableFurnitureElement.name.Contains("Office"))
                            Debug.Log("");
                        int randomValue = UnityEngine.Random.Range(0, possibleParentsFaces.Count);
                        PossibleParent chosenParent = possibleParentsFaces[randomValue];

                        GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

                        gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred

                        //Component gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement.GetComponent<FurniturePiece>(), new Vector3(0, 0, 0), Quaternion.identity) as Component;

                        furnitureListThird.Add(gameObjectTemp);

                        List<GameObject> furnitureChildren2nd3rd = new List<GameObject>(); //Combining the 2 lists
                        furnitureChildren2nd3rd.AddRange(furnitureListSecond);
                        furnitureChildren2nd3rd.AddRange(furnitureListThird);

                        if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(chosenParent.childFace, chosenParent.childFaceNo, chosenParent.parentFurnitureComponent, definiteFloor, doorPlaceholderGOs, furnitureListRoot, furnitureChildren2nd3rd, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
                        {
                            suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
                        }
                        //else
                            //GameObject.Destroy(gameObjectTemp);


                        if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
                            break;
                        loopCounter++;

                    }

                }

                possibleParentsFaces.Clear();
            }


            //bool definitiveMaxNumberSet = false;
            //foreach (GameObject placedFurnitureElement in furnitureListSecond)
            //{
            //    int loopCounter = 0;
            //    while (loopCounter < 5)
            //    {

            //        foreach (GameObject suitableFurnitureElement in suitableFurniture)
            //        {
            //            //List<MultiDimensionalFace> supportedFaces = new List<MultiDimensionalFace>(); //TODO: could be used if chairs, that have 4 constraints on one face for the table, want to be placed randomly on the edges
            //            if (!definitiveMaxNumberSet)
            //            {
            //                //suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(UnityEngine.Random.Range(2, suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesAsChild()));
            //                suitableFurnitureElement.GetComponent<FurniturePiece>().SetDefinitiveMaxNumber(7);
            //                Debug.Log(suitableFurnitureElement.name + " maxNumber: " + suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber());
            //                Debug.Log(suitableFurnitureElement.name + " maxInstancesAsChild " + suitableFurnitureElement.GetComponent<FurniturePiece>().GetMaxInstancesAsChild());
            //            }
            //            Component one = placedFurnitureElement.GetComponent<FurniturePiece>();
            //            Component two = suitableFurnitureElement.GetComponent<FurniturePiece>();

            //            foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face0)
            //            {
            //                if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
            //                    break;
            //                if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
            //                {
            //                    //supportedFaces.Add(face);

            //                    GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

            //                    gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred

            //                    //Component gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement.GetComponent<FurniturePiece>(), new Vector3(0, 0, 0), Quaternion.identity) as Component;

            //                    furnitureListThird.Add(gameObjectTemp);
            //                    FurniturePiece alooooo = gameObjectTemp.GetComponent<FurniturePiece>();
            //                    if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 0, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
            //                    {
            //                        suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
            //                    }
            //                    else
            //                        GameObject.Destroy(gameObjectTemp);
            //                }
            //            }
            //            foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face1)
            //            {
            //                if (suitableFurnitureElement.GetComponent<FurniturePiece>().GetExistingInstances() >= suitableFurnitureElement.GetComponent<FurniturePiece>().GetDefinitiveMaxNumber())
            //                    break;
            //                if (face.furniture.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().GetFurnitureType()))
            //                {
            //                    //supportedFaces.Add(face);

            //                    GameObject gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

            //                    gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
            //                    furnitureListThird.Add(gameObjectTemp);

            //                    //if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
            //                    //{
            //                    //    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
            //                    //}
            //                    //else
            //                    //    GameObject.Destroy(gameObjectTemp);
            //                    gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true);
            //                    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();


            //                    // gameObjectTemp = GameObject.Instantiate(suitableFurnitureElement, new Vector3(0, 0, 0), suitableFurnitureElement.transform.rotation) as GameObject;

            //                    //gameObjectTemp.GetComponent<FurniturePiece>().SetChangeableProperties(suitableFurnitureElement.GetComponent<FurniturePiece>().GetChangeableProperties()); //because Instantiate resets the added script, the changed values have to be transferred
            //                    //furnitureListThird.Add(gameObjectTemp);

            //                    //if (gameObjectTemp.GetComponent<FurniturePiece>().MoveTo(face, 1, placedFurnitureElement.GetComponent<FurniturePiece>(), doorPlaceholderGOs, furnitureListRoot, furnitureListSecond, true)) //for face1, pass the face of the child object, where the constraint is, and the planned parent                    
            //                    //{
            //                    //    suitableFurnitureElement.GetComponent<FurniturePiece>().AddInstance();
            //                    //}
            //                    //else
            //                    //    GameObject.Destroy(gameObjectTemp);

            //                    //gameObjectTemp.TestForCollision(placedFurnitureElement);
            //                    //yield return new WaitForSeconds(1f);
            //                    //yield return new WaitForEndOfFrame();

            //                    //yield return new WaitForEndOfFrame();

            //                    //yield return new WaitForEndOfFrame();
            //                    //yield return null;
            //                    //gameObjectTemp.GetComponent<FurniturePiece>().CheckForCollisions();
            //                }
            //            }
            //            //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face2)
            //            //{
            //            //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
            //            //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 2, placedFurniture.GetComponent<FurniturePiece>());
            //            //}
            //            //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face3)
            //            //{
            //            //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
            //            //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 3, placedFurniture.GetComponent<FurniturePiece>());
            //            //}
            //            //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face4)
            //            //{
            //            //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
            //            //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 4, placedFurniture.GetComponent<FurniturePiece>());
            //            //}
            //            //foreach (MultiDimensionalFace face in suitableFurnitureElement.GetComponent<FurniturePiece>().face5)
            //            //{
            //            //    if (face.furniture.Equals(placedFurniture.GetComponent<FurniturePiece>().furnitureType))
            //            //        suitableFurnitureElement.GetComponent<FurniturePiece>().MoveTo(face, 5, placedFurniture.GetComponent<FurniturePiece>());
            //            //}

            //        }
            //        definitiveMaxNumberSet = true;
            //        loopCounter++;
            //    }
            //}

        List<GameObject> furnitureGroup = new List<GameObject>();
        //foreach (GameObject placedFurnitureElement in furnitureListThird)
        //{
        //    foreach (GameObject _placedFurnitureElement in furnitureListThird)
        //    {
        //        if((Vector3.Distance(placedFurnitureElement.transform.position, _placedFurnitureElement.transform.position) < groupPlacementDistance) 
        //            && placedFurnitureElement.GetComponent<FurniturePiece>().furnitureType.Equals(_placedFurnitureElement.GetComponent<FurniturePiece>().furnitureType)) //TODO: kann auch nach go.name unterschieden werden
        //        {
        //            furnitureGroup.Add(_placedFurnitureElement);
        //            _placedFurnitureElement.GetComponent<FurniturePiece>().addedToGroup = true;
        //        }
        //    }
        //    if (furnitureGroup.Count > 0)
        //        OrderGroup(furnitureGroup);
        //    furnitureGroup.Clear();

        //}

        for (int i = 0; i < furnitureListRoot.Count; i++)
        {
            GameObject.Destroy(furnitureListRoot[i].gameObject);
        }



        foreach (GameObject _doorPlaceHolder in doorPlaceholderGOs) //
        {
            GameObject.Destroy(_doorPlaceHolder);
        }

        List<GameObject> allFurniture = new List<GameObject>();
        allFurniture.AddRange(furnitureListSecond);
        allFurniture.AddRange(furnitureListThird);
        foreach (GameObject go in allFurniture) //
        {
            if (!go.name.Contains("Table"))
                go.GetComponent<FurniturePiece>().SwitchColliders();
        }

    }

    private void OrderGroup(List<GameObject> _furnitureGroup)
    {
        while (true)
        {
            int listCountBefore = _furnitureGroup.Count;
            for (int i = 0; i < _furnitureGroup.Count; i++)
            {
                foreach (GameObject placedFurnitureElement in furnitureListThird)
                {
                    if ((Vector3.Distance(_furnitureGroup[i].transform.position, placedFurnitureElement.transform.position) < groupPlacementDistance)
                        && _furnitureGroup[i].GetComponent<FurniturePiece>().furnitureType.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().furnitureType)
                        && !placedFurnitureElement.GetComponent<FurniturePiece>().addedToGroup) //TODO: kann auch nach go.name unterschieden werden
                    {
                        _furnitureGroup.Add(placedFurnitureElement);
                        placedFurnitureElement.GetComponent<FurniturePiece>().addedToGroup = true;
                    }
                }
            }
            if (_furnitureGroup.Count == listCountBefore) //if no item has been added, the algorithm is finished
                break;
        }



        foreach (GameObject groupElement in _furnitureGroup)
        {
            foreach (GameObject placedFurnitureElement in furnitureListThird)
            {
                if ((Vector3.Distance(groupElement.transform.position, placedFurnitureElement.transform.position) < groupPlacementDistance)
                    && groupElement.GetComponent<FurniturePiece>().furnitureType.Equals(placedFurnitureElement.GetComponent<FurniturePiece>().furnitureType)
                    && !placedFurnitureElement.GetComponent<FurniturePiece>().addedToGroup) //TODO: kann auch nach go.name unterschieden werden
                {
                    _furnitureGroup.Add(placedFurnitureElement);
                    placedFurnitureElement.GetComponent<FurniturePiece>().addedToGroup = true;
                }
            }
        }
    }

    private void InsertDoorPlaceHolders()
    {
        foreach (Point placeHolderElement in doorPlaceHolders)
        {
            GameObject temp = GameObject.CreatePrimitive(PrimitiveType.Cube);
            temp.renderer.enabled = false;
            temp.transform.position = new Vector2(placeHolderElement.x, placeHolderElement.y);
            doorPlaceholderGOs.Add(temp);
        }
    }

    private void InsertFloor(List<GameObject> _floor)
    {
        definiteFloor = GameObject.Instantiate(_floor[0], new Vector3(0, 0, 0), Quaternion.identity) as GameObject;
        definiteFloor.AddComponent<FurniturePiece>();
        definiteFloor.GetComponent<FurniturePiece>().SetFurnitureType(FurnitureType.Floor);
        definiteFloor.transform.localScale = new Vector3(width, height, definiteFloor.transform.localScale.z);
        definiteFloor.transform.position = new Vector3(centerX + ((float)DataStorage.Instance.GetTileWidth() / 2), centerY, DataStorage.Instance.GetWallHeight()/2);
        definiteFloor.renderer.material.mainTextureScale = new Vector2(width, height);
        definiteFloor.name = "floor";
        definiteFloor.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions();

        //GameObject wall = Instantiate(wallCube, new Vector2(roomElement.GetXLeft() + (float)(roomElement.GetWidth() - 1) / 2, roomElement.GetYTop() + offset), Quaternion.identity) as GameObject;
        //wall.transform.localScale = new Vector3(roomElement.GetWidth(), 1, 1);
        //wall.renderer.material.mainTextureScale = new Vector2(roomElement.GetWidth(), 1);
        //wall.name = "room";
        ////Bottom Wall
        //wall = Instantiate(wallCube, new Vector2(roomElement.GetXLeft() + (float)(roomElement.GetWidth() - 1) / 2, roomElement.GetYBottom() - offset), Quaternion.identity) as GameObject;
        //wall.transform.localScale = new Vector3(roomElement.GetWidth(), 1, 1);
        //wall.renderer.material.mainTextureScale = new Vector2(roomElement.GetWidth(), 1);
        //wall.name = "room";
        ////Left Wall
        //wall = Instantiate(wallCube, new Vector2(roomElement.GetXLeft() - offset, roomElement.GetYTop() - (float)(roomElement.GetHeight() - 1) / 2), Quaternion.identity) as GameObject;
        //wall.transform.localScale = new Vector3(1, roomElement.GetHeight(), 1);
        //wall.renderer.material.mainTextureScale = new Vector2(1, roomElement.GetHeight());
        //wall.name = "room";
        ////Right Wall
        //wall = Instantiate(wallCube, new Vector2(roomElement.GetXRight() + offset, roomElement.GetYTop() - (float)(roomElement.GetHeight() - 1) / 2), Quaternion.identity) as GameObject;
        //wall.transform.localScale = new Vector3(1, roomElement.GetHeight(), 1);
        //wall.renderer.material.mainTextureScale = new Vector2(1, roomElement.GetHeight());
        //wall.name = "room";
    }

    private void InsertTempWallObjects()
    {
        //Top Wall
        GameObject wallTop = GameObject.CreatePrimitive(PrimitiveType.Cube);
        wallTop.AddComponent<FurniturePiece>();
        wallTop.GetComponent<FurniturePiece>().SetFurnitureType(FurnitureType.Wall);
        wallTop.transform.position = new Vector2(this.xLeft + (float)(this.GetWidth() - 1) / 2, this.GetYTop());
        wallTop.transform.localScale = new Vector3(this.GetWidth(), 1, 1);
        wallTop.name = "exampleWall";
        wallTop.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions();
        wallTop.GetComponent<Renderer>().enabled = false;
        //wallTop.GetComponent<Collider>().enabled = false;
        furnitureListRoot.Add(wallTop);//TODO: wegmachen und andere walls in liste aufnehmen
        //furnitureListRoot.Add(wallTop);
        //furnitureListRoot.Add(wallTop);
        //furnitureListRoot.Add(wallTop);

        //Bottom Wall
        GameObject wallBottom = GameObject.CreatePrimitive(PrimitiveType.Cube);
        wallBottom.AddComponent<FurniturePiece>();
        wallBottom.GetComponent<FurniturePiece>().SetFurnitureType(FurnitureType.Wall);
        wallBottom.transform.position = new Vector2(this.GetXLeft() + (float)(this.GetWidth() - 1) / 2, this.GetYBottom());
        wallBottom.transform.localScale = new Vector3(this.GetWidth(), 1, 1);
        //wallBottom.transform.Rotate(Vector3.forward * 180);
        wallBottom.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions(); //TODO: wurde verschoben, war vorher unter RotateFurniture()       
        wallBottom.GetComponent<FurniturePiece>().RotateFurniture();
        wallBottom.GetComponent<FurniturePiece>().RotateFurniture();
        wallBottom.name = "exampleWall";
        wallBottom.GetComponent<Renderer>().enabled = false;
        //wallBottom.GetComponent<Collider>().enabled = false;
        furnitureListRoot.Add(wallBottom);

        //Left Wall
        GameObject wallLeft = GameObject.CreatePrimitive(PrimitiveType.Cube);
        wallLeft.AddComponent<FurniturePiece>();
        wallLeft.GetComponent<FurniturePiece>().SetFurnitureType(FurnitureType.Wall);
        wallLeft.transform.position = new Vector2(this.GetXLeft(), this.GetYTop() - (float)(this.GetHeight() - 1) / 2);
        wallLeft.transform.localScale = new Vector3(this.GetHeight(), 1, 1);
        wallLeft.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions(); //TODO: wurde verschoben, war vorher unter RotateFurniture()
        wallLeft.GetComponent<FurniturePiece>().RotateFurniture();
        wallLeft.name = "exampleWall";
        wallLeft.GetComponent<Renderer>().enabled = false;
        //wallLeft.GetComponent<Collider>().enabled = false;
        furnitureListRoot.Add(wallLeft);

        //Right Wall
        GameObject wallRight = GameObject.CreatePrimitive(PrimitiveType.Cube);
        wallRight.AddComponent<FurniturePiece>();
        wallRight.GetComponent<FurniturePiece>().SetFurnitureType(FurnitureType.Wall);
        wallRight.AddComponent<Rigidbody>();
        //wallRight.GetComponent<Rigidbody>().isKinematic = true;
        wallRight.transform.position = new Vector2(this.GetXRight(), this.GetYTop() - (float)(this.GetHeight() - 1) / 2);
        wallRight.transform.localScale = new Vector3(this.GetHeight(), 1, 1);
        wallRight.name = "rightWall";
        wallRight.GetComponent<FurniturePiece>().SetFaceNormalsAndPositions(); //TODO: wurde verschoben, war vorher unter RotateFurniture()
        wallRight.GetComponent<FurniturePiece>().RotateFurniture();
        wallRight.GetComponent<FurniturePiece>().RotateFurniture();
        wallRight.GetComponent<FurniturePiece>().RotateFurniture();
        wallRight.GetComponent<Renderer>().enabled = false;
        //wallRight.GetComponent<Collider>().enabled = false;
        furnitureListRoot.Add(wallRight);
    }

    public void SetRoomType(RoomType _roomType)
    {
        roomType = _roomType;
    }

    public int GetXLeft()
    {
        return xLeft;
    }

    public int GetXRight()
    {
        return xRight;
    }

    public int GetYTop()
    {
        return yTop;
    }

    public int GetYBottom()
    {
        return yBottom;
    }

    public int GetWidth()
    {
        return width;
    }

    public int GetHeight()
    {
        return height;
    }

    public Point GetCenter()
    {
        return center;
    }

    private void Clear()
    {
        doorPlaceholderGOs.Clear();

        furnitureListRoot.Clear();
        furnitureListSecond.Clear();
        furnitureListThird.Clear();
    }
}
